package com.linsen.oss.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.google.zxing.WriterException;
import com.linsen.core.common.exception.BaseException;
import com.linsen.core.common.util.QREncode;
import com.linsen.oss.props.FileProperties;
import com.linsen.oss.provider.vo.UploadFileData;
import com.linsen.oss.service.FileUploadService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

@Slf4j
@Service
@RequiredArgsConstructor
public class FileUploadServiceImpl implements FileUploadService {
    private static final List<String> IMAGE_TYPE = Arrays.asList("image/jpeg", "image/jpg", "image/png", "image/gif");

    private final FileProperties fileProperties;

    @Override
    public String uploadImg(MultipartFile file) {
        try {
            //校验文件类型
            String contentType = file.getContentType();
            if (!IMAGE_TYPE.contains(contentType)) {
                return "无效的文件类型";
            }
            //校验文件内容
            BufferedImage image = ImageIO.read(file.getInputStream());
            if (image == null) {
                System.out.println(file.getName());
                return "文件读取失败";
            }
            // 文件名
            String fileName = file.getOriginalFilename();
            // 后缀名
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //新名字
            String newFileName = UuidUtils.generateUuid() + suffixName;
            FileUtil.mkdir(fileProperties.getPath());
            File dest = new File(fileProperties.getPath() + newFileName);
            //保存文件到本地
            file.transferTo(dest);
            return newFileName;
        } catch (IOException e) {
            e.printStackTrace();
            return "文件上传失败";
        }
    }

    @Override
    public UploadFileData uploadImgInfo(MultipartFile file) throws Exception {
        //准备目标路径
        String host = fileProperties.getHost();
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }

        //校验文件类型
        String contentType = file.getContentType();
        if (!IMAGE_TYPE.contains(contentType)) {
            throw new Exception("无效的文件类型");
        }

        //校验文件内容
        BufferedImage image = ImageIO.read(file.getInputStream());
        if (image == null) {
            throw new Exception("文件读取失败");
        }

        UploadFileData uploadFileData = new UploadFileData();
        uploadFileData.setAttrType(contentType);
        uploadFileData.setAttrSize(file.getSize());
        // 文件名
        String fileName = file.getOriginalFilename();
        uploadFileData.setRealName(fileName);
        // 后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //新名字
        String newFileName = UuidUtils.generateUuid() + suffixName;
        uploadFileData.setName(newFileName);

        String createChildPath = createChildPath();
        // 创建文件路径
        FileUtil.mkdir(fileProperties.getPath() + createChildPath);
        File dest = new File(fileProperties.getPath() + createChildPath + newFileName);
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("文件上传失败");
        }
        uploadFileData.setAttrDir(host + createChildPath + newFileName);

        return uploadFileData;
    }

    @Override
    public String uploadFile(MultipartFile file) {
        if (ObjectUtil.isNull(file) || file.isEmpty()) {
            throw new BaseException("文件内容为空");
        }

        String host = fileProperties.getHost();
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }

        log.info("host: {}, upload file filename: {}, size: {}, type: {}", host, file.getOriginalFilename(), file.getSize(), file.getContentType());

        // 后缀名
        String suffixName = this.getSuffixName(file.getContentType());
        // 新名字
        String newFileName = UuidUtils.generateUuid() + StrUtil.DOT + suffixName;

        String createChildPath = createChildPath();
        // 创建文件路径
        FileUtil.mkdir(fileProperties.getPath() + createChildPath);
        File dest = new File(fileProperties.getPath() + createChildPath + newFileName);
        try {
            file.transferTo(dest);
            Runtime.getRuntime().exec("chmod 604 -R " + fileProperties.getPath() + createChildPath + newFileName);
        } catch (IOException e) {
            e.printStackTrace();
        }


        return host + createChildPath + newFileName;
    }

    @Override
    public String uploadFile(byte[] bytes, String suffix) {
        if (ObjectUtil.isEmpty(bytes)) {
            throw new BaseException("文件内容为空");
        }

        String host = fileProperties.getHost();
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }

        // 新名字
        String newFileName = UuidUtils.generateUuid() + StrUtil.DOT + suffix;

        String createChildPath = createChildPath();
        // 创建文件路径
        FileUtil.mkdir(fileProperties.getPath() + createChildPath);
        File dest = new File(fileProperties.getPath() + createChildPath + newFileName);
        FileUtil.writeBytes(bytes, dest);
        return host + createChildPath + newFileName;
    }

    @Override
    public UploadFileData uploadFileInfo(MultipartFile file) throws Exception {
        if (ObjectUtil.isNull(file) || file.isEmpty()) {
            throw new BaseException("文件内容为空");
        }

        //准备目标路径
        String host = fileProperties.getHost();
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }

        log.info("host: {}, upload file filename: {}, size: {}, type: {}", host, file.getOriginalFilename(), file.getSize(), file.getContentType());

        //校验文件类型
        String contentType = file.getContentType();

        //校验文件内容
        BufferedImage image = ImageIO.read(file.getInputStream());
        if (image == null) {
            throw new Exception("文件读取失败");
        }

        UploadFileData uploadFileData = new UploadFileData();
        uploadFileData.setAttrType(contentType);
        uploadFileData.setAttrSize(file.getSize());
        // 文件名
        String fileName = file.getOriginalFilename();
        uploadFileData.setRealName(fileName);
        // 后缀名
        String suffixName = this.getSuffixName(file.getContentType()); // fileName.substring(fileName.lastIndexOf("."));
        //新名字
        String newFileName = UuidUtils.generateUuid() + StrUtil.DOT + suffixName;
        uploadFileData.setName(newFileName);

        String createChildPath = createChildPath();
        // 创建文件路径
        FileUtil.mkdir(fileProperties.getPath() + createChildPath);
        File dest = new File(fileProperties.getPath() + createChildPath + newFileName);
        try {
            file.transferTo(dest);
            Runtime.getRuntime().exec("chmod 604 -R " + fileProperties.getPath() + createChildPath + newFileName);
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("文件上传失败");
        }
        uploadFileData.setAttrDir(host + createChildPath + newFileName);

        return uploadFileData;
    }

    @Override
    public String createQrCode(String content) {
        String suffix = "png";

        String host = fileProperties.getHost();
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }

        // 新名字
        String newFileName = UuidUtils.generateUuid() + StrUtil.DOT + suffix;

        String createChildPath = createChildPath();
        // 创建文件路径
        FileUtil.mkdir(fileProperties.getPath() + createChildPath);
        File dest = new File(fileProperties.getPath() + createChildPath + newFileName);

        try {
            QREncode.createQrCode(dest,content,300,suffix);
        } catch (Exception e) {
            throw new BaseException("二维码文件生成失败");
        }

        return host + createChildPath + newFileName;
    }

    /**
     * 根据随机数生成3级子目录，理论上存在36*36的3次方个分支
     */
    public String createChildPath() {
        Random random = new Random();
        StringBuilder sBuilder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int num = random.nextInt(36);
            sBuilder.append(Long.toString(num, 36));//把10进制数转为一个36进制的字符串
        }
        String numStr = sBuilder.toString();
        //System.out.println(numStr);
        //得到了一个6位的36进制数组成的字符(0-9,A-Z一共36种变化),每两位组成一个子路径
        String childPath = StrUtil.format("/{}/{}/{}/", numStr.substring(0, 2), numStr.substring(2, 4), numStr.substring(4, 6));
        return childPath;
    }

    private String getSuffixName(String type) {
        List<String> typeList = StrUtil.split(type, '/');
        if (CollUtil.isEmpty(typeList)) {
            throw new BaseException("文件类型为空");
        }

        return typeList.get(1);
    }
}